#pragma once

#ifndef ProcTable_h
#define ProcTable_h

#include <string>
#include <map>
#include <hash_map>
#include "Type.h"

class ProcTable{
private:
	typedef std::map<Type::Index::Proc, Type::Name::Proc> NameTableType;
	typedef std::map<Type::Name::Proc, Type::Index::Proc> IndexTableType;
	typedef std::map<Type::Index::Proc, Type::Pair::StartEnd> StartEndTableType;
	typedef std::map<Type::Index::Line, Type::Index::Proc> LineProcTableType;
	typedef std::hash_map<Type::Index::Proc, Type::List::Line> ProcExitPointsType;

	NameTableType nameTable;
	IndexTableType indexTable;
	StartEndTableType startEndTable;
	LineProcTableType lineProcTable;
	Type::Index::Proc index;
	ProcExitPointsType procExitTable;

public:
	ProcTable(void);
	~ProcTable(void);
	void clear();

	// insert procedure with its name, return procedure index
	Type::Index::Proc insertProc(Type::Name::Proc);
	// insert procedure with its starting & ending line index
	bool insertProcStartEnd(Type::Index::Proc, Type::Index::Line, Type::Index::Line);
	
	// get all procedure indices
	const Type::List::Proc& getProcIndices();
	// get procedure index with the given procedure name
	Type::Index::Proc getProcIndex(Type::Name::Proc);
	// get procedure name with the given procedure index
	Type::Name::Proc getProcName(Type::Index::Proc);
	// get starting & ending line of the given procedure index
	Type::Pair::StartEnd getProcStartEnd(Type::Index::Proc);
	// get the procedure index where the given line is located at
	Type::Index::Proc getProcIndexOfLine(Type::Index::Line);

	// check for procedure exsistence with the given procedure name
	bool isProcExistsInProcTable(Type::Name::Proc);
	// check for procedure exsistence with the given procedure index
	bool isProcExistsInProcTable(Type::Index::Proc);
	// check for procedure exsistence with the given procedure index
	bool isProcExistsInStartEnd(Type::Index::Proc);

	// set exit points
	bool setProcExitPoint(Type::Index::Proc, Type::Index::Line);
	// get exit points, empty list if none
	const Type::List::Line& getProcExitPoints(Type::Index::Proc);
};
#endif